<?php

namespace Leantime\Domain\Connector\Controllers {

    use Leantime\Core\Controller\Controller;
    use Leantime\Core\Controller\Frontcontroller;
    use Leantime\Domain\Auth\Models\Roles;
    use Leantime\Domain\Auth\Services\Auth;
    use Leantime\Domain\Connector\Models\Integration as IntegrationModel;
    use Leantime\Domain\Connector\Repositories\LeantimeEntities;
    use Leantime\Domain\Connector\Services\Connector;
    use Leantime\Domain\Connector\Services\Integrations as IntegrationService;
    use Leantime\Domain\Connector\Services\Providers;

    class Integration extends Controller
    {
        private Providers $providerService;

        private IntegrationService $integrationService;

        private LeantimeEntities $leantimeEntities;

        private array $values = [];

        private array $fields = [];

        private Connector $connectorService;

        /**
         * constructor - initialize private variables
         */
        public function init(
            Providers $providerService,
            IntegrationService $integrationService,
            LeantimeEntities $leantimeEntities,
            Connector $connectorService
        ) {
            Auth::authOrRedirect([Roles::$owner, Roles::$admin], true);

            $this->providerService = $providerService;
            $this->leantimeEntities = $leantimeEntities;
            $this->integrationService = $integrationService;
            $this->connectorService = $connectorService;
        }

        /**
         * run - handle post
         */
        public function run()
        {

            $params = $_REQUEST;
            if (! session()->exists('currentImportEntity')) {
                session(['currentImportEntity' => '']);
            }

            if (isset($params['provider'])) {
                // New integration with provider
                // Get the provider
                $provider = $this->providerService->getProvider($params['provider']);
                $this->tpl->assign('provider', $provider);

                $currentIntegration = app()->make(IntegrationModel::class);

                if (isset($params['integrationId'])) {
                    $currentIntegration = $this->integrationService->get($params['integrationId']);
                    $this->tpl->assign('integrationId', $currentIntegration->id);
                }

                /* Steps + + + + + + + + + + + + + + + + + + + + + + + */

                // STEP 0: No Step defined, new integration
                if (! isset($params['step'])) {
                    return $this->tpl->display('connector.newIntegration');
                }

                // STEP 1: Initiate connection
                if ($params['step'] == 'connect') {
                    // This should handle connection UI
                    $connection = $provider->connect();

                    if ($connection instanceof \Symfony\Component\HttpFoundation\Response) {
                        return $connection;
                    }
                }

                // STEP 2: Choose Entities to sync
                if ($params['step'] == 'entity') {
                    $this->tpl->assign('providerEntities', $provider->getEntities());
                    $this->tpl->assign('leantimeEntities', $this->leantimeEntities->availableLeantimeEntities);

                    // TODO UI to show entity picker/mapper
                    return $this->tpl->display('connector.integrationEntity');
                }

                // STEP 3: Choose Entities to sync
                if ($params['step'] == 'fields') {
                    if (isset($_POST['leantimeEntities'])) {
                        $entity = $_POST['leantimeEntities'];
                        session(['currentImportEntity' => $entity]);
                    } elseif (session()->exists('currentImportEntity') && session('currentImportEntity') != '') {
                        $entity = session('currentImportEntity');
                    } else {
                        $this->tpl->setNotification('Entity not set', 'error');

                        return Frontcontroller::redirect(BASE_URL.'/connector/integration?provider='.$provider->id.'');
                    }

                    $currentIntegration->entity = $entity;

                    $flags = $this->connectorService->getEntityFlags($entity);

                    $this->integrationService->patch($currentIntegration->id, ['entity' => $entity]);

                    if (isset($currentIntegration->fields) && $currentIntegration->fields != '') {
                        $this->tpl->assign('providerFields', explode(',', $currentIntegration->fields));
                    } else {
                        $this->tpl->assign('providerFields', $provider->getFields());
                    }
                    $this->tpl->assign('flags', $flags);
                    $this->tpl->assign('leantimeFields', $this->leantimeEntities->availableLeantimeEntities[$entity]['fields']);

                    return $this->tpl->display('connector.integrationFields');
                }

                // STEP 4: Choose Entities to sync
                if ($params['step'] == 'sync') {
                    // TODO UI to show sync schedule/options
                    return $this->tpl->display('connector.integrationSync');
                }

                // STEP 5: import Review
                if ($params['step'] == 'parse') {
                    $this->values = $provider->geValues();

                    // Fetching the field matching and putting it in an array
                    $this->fields = [];
                    $this->fields = $this->connectorService->getFieldMappings($_POST);

                    $flags = [];
                    $flags = $this->connectorService->parseValues($this->fields, $this->values, session('currentImportEntity'));

                    // show the imported data as confirmation
                    $this->tpl->assign('values', $this->values);
                    $this->tpl->assign('fields', $this->fields);
                    $this->tpl->assign('flags', $flags);

                    return $this->tpl->display('connector.integrationImport');
                }

                // STEP 6: Do the import
                if ($params['step'] == 'import') {
                    // Store data in DB
                    $values = unserialize(session('serValues'));
                    $fields = unserialize(session('serFields'));

                    // confirm and store in DB
                    $result = $this->connectorService->importValues($fields, $values, session('currentImportEntity'));

                    if ($result !== true) {
                        $this->tpl->setNotification('There was a problem with the import '.$result, 'error');
                    }

                    // display stored successfully message
                    return $this->tpl->display('connector.integrationConfirm');
                }
            }
        }
    }
}
